/**
 * @param {string} tag
 */
export default class VNode {
    tag; // 标签名
    data; 
    children; // 保存子VNode

    /**
     * 
     * @param {?string} tag - 当前节点的标签名
     * @param {?VNodeData} data - 当前节点对应的对象，包含了具体的一些数据信息
     * @param {?Array<VNode>} children - 当前虚拟节点的子虚拟节点
     * @param {?string} text - 当前节点的文本
     * @param {?Node} elm - 当前虚拟节点对应的真实dom节点
     * @param {?Component} context - 当前组件节点对应的Vue实例
     * @param {?VNodeComponentOptions} componentOptions - 组件的option选项
     * @param {?Function} asyncFactory -
     */
    constructor (tag,data,children,text,elm,context,componentOptions,asyncFactory){
        this.tag = tag; // 当前节点的标签名
        this.data = data; // 当前节点对应的对象，包含了具体的一些数据信息
        this.children = children; // 子节点，是一个数组Array<VNode>
        this.text = text; // 当前节点的文本
        this.elm = elm; // 当前虚拟节点对应的真实dom节点
        this.ns = undefined; /*当前节点的名字空间*/
        this.context = context; // 当前组件节点对应的vue实例
        this.fnContext = undefined; // 函数式组件对应的vue实例
        this.fnOptions = undefined;
        this.fnScopeId = undefined;

        this.key = data && data.key; // 节点的key属性，被当做节点的标志，用以优化（for循环会用到）
        this.componentOptions = componentOptions; // 组件的option选项
        this.componentInstance = undefined; // 当前节点对应的组件实例
        this.parent = undefined; // 当前节点的父节点
        this.raw = false;    // 是原生HTML还是普通文本，innerHTML的时候为true，textContent的时候为false
        this.isStatic = false; // 静态节点标志
        this.isRootInsert = true; // 是否作为根节点插入
        this.isComment = false; // 是否是注释节点
        this.isCloned = false; // 是否为克隆节点
        this.isOnce = false; // 是否具有v-once指令
        this.asyncFactory = asyncFactory;
        this.asyncMeta = undefined;
        this.isAsyncPlaceholder = false;
    }
    // DEPRECATED: alias for componentInstance for backwards compat.
    // 已被废弃
    get child(){
        return this.componentInstance;
    }
}


// 创建一个注释节点
export const createEmptyVNode = (text)=>{
    if(text === void 0){ text = '' };
    const node = new VNode();
    node.isComment = true;
    node.text = text;
    return node;
}

// 创建一个文本节点
export function createTextVNode(val){
    return new VNode(undefined,unedfined,unedfined,String(val))
}

// optimized shallow clone
// used for static nodes and slot nodes because they may be reused across
// multiple renders, cloning them avoids errors when DOM manipulations rely
// on their elm reference.
/**
 * 优化了用于克隆静态节点和插槽节点的浅克隆，因为他们可以在多个地方复用，克隆它们可以避免DOM操作依赖于它们的elm引用时出现错误
 * @param {VNode} vnode 
 */
// 克隆一个节点
export function cloneVNode(vnode){
    const cloned = new VNode(
        vnode.tag,
        vnode.data,
        // #7975
        // clone children array to avoid mutating original in case of cloning
        // a child.
        // 将子节点使用slice进行浅克隆
        vnode.children && vnode.children.slice(),
        vnode.text,
        vnode.elm,
        vnode.context,
        vnode.componentOptions,
        vnode.asyncFactory
    )
    cloned.ns = vnode.ns; // 克隆节点名字空间
    cloned.isStatic = vnode.isStatic;
    cloned.key = vnode.key;
    cloned.isComment = vnode.isComment;
    cloned.fnContext = vnode.fnContext;
    cloned.fnOptions = vnode.fnOptions;
    cloned.fnScopeId = vnode.fnScopeId;
    cloned.asyncMeta = vnode.asyncMeta;
    cloned.isCloned = true;
    return cloned;
}